package com.msb.mall.ware.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.msb.common.dto.WareHasStockDTO;
import com.msb.common.exception.NoStockExecption;
import com.msb.common.utils.PageUtils;
import com.msb.common.utils.Query;
import com.msb.common.utils.R;
import com.msb.mall.ware.dao.WareSkuDao;
import com.msb.mall.ware.entity.WareSkuEntity;
import com.msb.mall.ware.feign.ProductFeignService;
import com.msb.mall.ware.service.WareSkuService;
import com.msb.mall.ware.vo.OrderItemVo;
import com.mysql.cj.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {
    @Autowired
    private ProductFeignService productFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<WareSkuEntity> wrapper = new QueryWrapper<>();

        String skuId = (String) params.get("skuId");
        if (!StringUtils.isNullOrEmpty(skuId)){
            wrapper.eq("sku_id",skuId);
        }

        String wareId = (String) params.get("wareId");
        if (!StringUtils.isNullOrEmpty(wareId)){
            wrapper.eq("ware_id",wareId);
        }
        IPage<WareSkuEntity> page = this.page(
                new Query<WareSkuEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    /**
     * 采购成功-入库操作
     * @param skuId 采购商品id
     * @param wareId 仓库id
     * @param skuNum 采购数量
     */
    @Override
    public void toStock(Long skuId, Long wareId, Integer skuNum) {
        // 判断是否存在该库存数据，是：修改，否：插入
        List<WareSkuEntity> list = this.list(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
        if (null == list || list.size() == 0){
            // 插入
            WareSkuEntity wareSkuEntity = new WareSkuEntity();
            wareSkuEntity.setSkuId(skuId);
            wareSkuEntity.setWareId(wareId);
            wareSkuEntity.setStock(skuNum);
            wareSkuEntity.setStockLocked(0);
            try {
                R info = productFeignService.info(skuId); // 通过openFeign远程调用商品服务
                Map<String,Object> skuInfo = (Map<String, Object>) info.get("skuInfo");
                wareSkuEntity.setSkuName((String) skuInfo.get("skuName"));
            }catch (Exception e){
                e.printStackTrace();
            }
            this.save(wareSkuEntity);
        }else {
            // 修改
            this.update().setSql("stock=stock+"+skuNum).eq("sku_id", skuId).eq("ware_id", wareId).update();
        }
    }

    /**
     * 根据skuId集合批量查询是否有库存
     * @param skuIds
     * @return
     */
    @Override
    public List<WareHasStockDTO> isHasStock(List<Long> skuIds) {
        List<WareHasStockDTO> list = skuIds.stream().map(skuId -> {
            Long count = baseMapper.getSkuStock(skuId);
            if (null == count){
                count = 0L;
            }
            WareHasStockDTO wareHasStockDTO = new WareHasStockDTO();
            wareHasStockDTO.setSkuId(skuId);
            wareHasStockDTO.setHasStock(count > 0);
            return wareHasStockDTO;
        }).collect(Collectors.toList());

        return list;
    }

    /**
     * 锁定库存
     * @param skuItems
     * @return
     */
    @Transactional
    @Override
    public Boolean lockStock(List<OrderItemVo> skuItems) {
        for (OrderItemVo item : skuItems) {
            List<WareSkuEntity> wareList = this.list(new QueryWrapper<WareSkuEntity>().eq("sku_id", item.getSkuId()));
            // 需锁定的库存
            Integer count = item.getCount();
            if (null != wareList || wareList.size() > 0){
                for (WareSkuEntity ware : wareList) {
                    // 现存库存
                    int stock = ware.getStock() - ware.getStockLocked();
                    if (count <= stock){
                        // 库存充足
                        this.baseMapper.lockSkuStock(item.getSkuId(),ware.getWareId(),count);
                        count = 0;
                    }else {
                        // 库存不足--锁定可以锁定的库存
                        this.baseMapper.lockSkuStock(item.getSkuId(),ware.getWareId(),stock);
                        count -= stock;
                    }
                    if (count <=0 ){
                        // 需要锁定的库存已全部锁定
                        break;
                    }
                }
                if (count > 0){
                    // 库存没有锁定完成
                    throw new NoStockExecption(item.getSkuId());
                }
            }else {
                // 该商品没有库存
                throw new NoStockExecption(item.getSkuId());
            }

        }

        return true;
    }

}